class Ssp::Report < ApplicationRecord
  belongs_to :user
  validates_presence_of :user, :publish_at

  has_many :report_items
  accepts_nested_attributes_for :report_items, allow_destroy: true

  STATUS = { '未审核': :unconfirmed, '已审核': :confirmed, '已同步': :reported }

  attr_accessor :_check

  before_save :calculate_values
  def calculate_values
    self.items_count = report_items.size
    self.price_sum = report_items.map(&:price).sum
    self.count_sum = report_items.map(&:count).sum
  end

  after_initialize do
    self.status ||= 'unconfirmed'
    self.publish_at ||= Time.now
  end

  def self.report!
    county_types = { 'country' => 1, 'town' => 2, 'village' => 3 }

    client = Savon.client(wsdl: "http://211.88.20.132:8040/services/syncServiceStation?wsdl")
    reports = self.includes(:user, :report_items).where(status: 'confirmed').where('publish_at < ?', Time.now)

    reports.group_by do |report|
      report.user.cid
    end.each do |cid, reports|
      reports.group_by do |report|
        report.publish_at.strftime('%Y-%m-%d')
      end.each do |date, reports|
        params = {
          service_station: {
            user_id: cid,
            rpt_date: date,
            service_station_report: reports.map do |report|
              grouped_items = report.report_items.group_by do |item|
                item.commodity_type
              end

              {
                code: report.user.ssid,
                name: report.user.nickname,
                county_type: county_types[report.user.sstype],
                buy_order: (grouped_items['buy'] || []).map(&:count).sum,
                sale_order: (grouped_items['sale'] || []).map(&:count).sum,
                service_station_commodity: report.report_items.map do |item|
                  {
                    comm_id: item.commodity_id_for_report,
                    money: item.price,
                  }
                end
              }
            end
          }
        }

        message = { in: Gyoku.xml(params) }
        puts "Call sync_service_station_operation with message #{message}"

        tries = 5
        begin
          client.call(:sync_service_station_operation, message: message)
        rescue Net::ReadTimeout => error
          unless (tries -= 1).zero?
            puts "Net::ReadTimeout: retry ##{tries} in 5 seconds"
            sleep 5
            retry
          end
        else
          puts "Update #{reports.size} reports"
          self.where(id: reports).update_all(reported_at: Time.now, status: 'reported')
        end
      end
    end
  end
end
